#include "RenderingThreadContext.h"
#include "RunnableTask.h"
#include "RunnableTaskEvent.h"
#include "ThreadPool.h"
#include "Runtime/Platform/PlatformAPI.h"
#include "Runtime/Log/Logger.h"
#include "GL/glew.h"
#include "GL/wglew.h"
#pragma comment(lib,"opengl32.lib")

namespace Alice
{
	bool IsInRenderingThread()
	{
		return PlatformTLS::GetCurrentThreadId() == Thread::RenderThreadID;
	}
	RenderingThreadContext * GRenderingThreadContext=nullptr;
	Thread*GRenderingThread=nullptr;
	bool GIsRunningRHIInSeparateThread_InternalUseOnly=false;
	bool FORCEINLINE IsRunningRHIInSeparateThread()
	{
		return GIsRunningRHIInSeparateThread_InternalUseOnly;
	}
	static int32 FlushRHILogsAndReportCrash(LPEXCEPTION_POINTERS ExceptionInfo)
	{
		return 0;
	}
	void RenderingThreadMain(SmartPtr<Event>& inRenderThreadContextReadyEvent)
	{
		//let the main thread go, wait for render thread init complete to trigger event
		std::this_thread::sleep_for(std::chrono::microseconds(16));
		ENamedThreads RenderThread = ENamedThreads::ActualRenderingThread;
		SetRenderThread(RenderThread);
		SetRenderThread_Local(ENamedThreads::ActualRenderingThread_Local);
		ThreadPoolInterface::Get().AttachToThread(RenderThread);
		if(inRenderThreadContextReadyEvent != NULL )
		{
			inRenderThreadContextReadyEvent->TriggerOne();
		}
		//Debug("Start Process render command %d",inRenderThreadContextReadyEvent->mReferenceCount);
		ThreadPool::Get().ProcessThreadUntilManualStop(RenderThread);
		//Debug("End Process render command");
		SetRenderThread(ENamedThreads::GameThread);
		SetRenderThread_Local(ENamedThreads::GameThread_Local);
	}
	bool RenderingThreadContext::Init() {
		Thread::RenderThreadID = PlatformTLS::GetCurrentThreadId();
        //InitCGI(GetModuleHandleW(nullptr));
		//BOOL Result = wglMakeCurrent(OpenGLDevice::mCurrentOpenGLDevice.mHandleDeviceContext, OpenGLDevice::mCurrentOpenGLDevice.mRenderContext);
		/*if (!Result)
		{
			Error("RenderingThreadContext::Init %d %p %p Failed[%d] %p,%p\n", 
				AliceThreadEX::RenderThreadID, 
				OpenGLDevice::mCurrentOpenGLDevice.mHandleDeviceContext, 
				OpenGLDevice::mCurrentOpenGLDevice.mRenderContext,
				GetLastError(),wglGetCurrentDC(),wglGetCurrentContext());
		}*/
		return true;
	}
	uint32 RenderingThreadContext::Run()
	{
		//Debug("RenderingThreadContext::Run start [%d]",mReadyEvent->mReferenceCount);
		RenderingThreadMain(mReadyEvent);
		//Debug("RenderingThreadContext::Run end [%d]",mReadyEvent->mReferenceCount);
		return 0;
	}

    void StartRenderingThread()
	{
		GRenderingThreadContext = new RenderingThreadContext();
    	GRenderingThread=Thread::Create("RenderThread",GRenderingThreadContext);
		GRenderingThreadContext->mReadyEvent->Wait();
	}


	void StopRenderingThread()
	{
		RunnableTaskEventRef QuitTask = TRunnableTask<ThreadReturnTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(GetRenderThread());
		while ((QuitTask!= nullptr) && !QuitTask->IsComplete())
		{
			Sleep(0);
		}
		GRenderingThread->WaitForCompletion();
		delete GRenderingThread;
		GRenderingThread = nullptr;
		delete GRenderingThreadContext;
		GRenderingThreadContext = nullptr;
	}
}
